using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;
using EnvDTE80;

namespace Koda.Model
{
    public class Member
    {
        private string name;
        private MemberInfo info;

        public MemberInfo Info
        {
            get
            {
                return this.info;
            }
        }
	
        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                this.name = value;
            }
        }

        public Member()
        {
            this.name = String.Empty;
            this.info = new MemberInfo();
        }

        public override int GetHashCode()
        {
            return this.name.GetHashCode() ^ this.info.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            Member member = obj as Member;
            if (member == null)
                return false;

            if (member.name == this.name && member.info == this.info)
                return true;

            return false;
        }

        public static Member FromCodeElement(CodeElement codeElement)
        {
            Member member = new Member();
            member.Name = codeElement.Name;

            switch (codeElement.Kind)
            {
                case vsCMElement.vsCMElementFunction:
                    CodeFunction2 codeFunction = (CodeFunction2)codeElement;
                    member.Info.Access = GetMemberAccess(codeFunction.Access);
                    if (codeFunction.IsShared)
                        member.Info.Scope = MemberScope.Static;
                    else
                        member.Info.Scope = MemberScope.Instance;

                    if (codeFunction.FunctionKind == vsCMFunction.vsCMFunctionConstructor)
                        member.Info.Type = MemberType.Constructor;
                    else
                        member.Info.Type = MemberType.Function;
                    break;

                case vsCMElement.vsCMElementVariable:
                    CodeVariable2 codeVariable = (CodeVariable2)codeElement;
                    member.Info.Access = GetMemberAccess(codeVariable.Access);
                    if (codeVariable.IsConstant)
                    {
                        member.Info.Type = MemberType.Constant;
                        member.Info.Scope = MemberScope.Static;
                    }
                    else
                    {
                        member.Info.Type = MemberType.Variable;
                        if (codeVariable.IsShared)
                            member.Info.Scope = MemberScope.Static;
                    }

                    break;

                case vsCMElement.vsCMElementProperty:
                    CodeProperty codeProperty = (CodeProperty)codeElement;
                    member.Info.Access = GetMemberAccess(codeProperty.Access);
                    member.Info.Type = MemberType.Property;
                    if ((codeProperty.Setter != null && codeProperty.Setter.IsShared) || (codeProperty.Getter != null && codeProperty.Getter.IsShared))
                        member.Info.Scope = MemberScope.Static;
                    break;

                case vsCMElement.vsCMElementDelegate:
                    CodeDelegate codeDelegate = (CodeDelegate)codeElement;
                    member.Info.Access = GetMemberAccess(codeDelegate.Access);
                    member.Info.Type = MemberType.Delegate;
                    break;

                case vsCMElement.vsCMElementEvent:
                    CodeEvent codeEvent = (CodeEvent)codeElement;
                    member.Info.Access = GetMemberAccess(codeEvent.Access);
                    member.Info.Type = MemberType.Event;
                    break;

                case vsCMElement.vsCMElementEnum:
                    CodeEnum codeEnum = (CodeEnum)codeElement;
                    member.Info.Access = GetMemberAccess(codeEnum.Access);
                    member.Info.Type = MemberType.Enum;
                    break;

                case vsCMElement.vsCMElementClass:
                    CodeClass codeClass = (CodeClass)codeElement;
                    member.Info.Access = GetMemberAccess(codeClass.Access);
                    member.Info.Type = MemberType.Class;
                    break;

                case vsCMElement.vsCMElementStruct:
                    CodeStruct codeStruct = (CodeStruct)codeElement;
                    member.Info.Access = GetMemberAccess(codeStruct.Access);
                    member.Info.Type = MemberType.Struct;
                    break;
            }

            return member;
        }

        private static MemberAccess GetMemberAccess(vsCMAccess access)
        {
            switch (access)
            {
                case vsCMAccess.vsCMAccessPublic:
                    return MemberAccess.Public;
                case vsCMAccess.vsCMAccessPrivate:
                    return MemberAccess.Private;
                case vsCMAccess.vsCMAccessProtected:
                    return MemberAccess.Protected;
                default:
                    return MemberAccess.Other;
            }
        }
	
    }
}
